package pl.engine
{
	
	import pl.engine.camera.Camera;
	import pl.engine.camera.ICameraIsoParams;
	import pl.engine.model.IModel;
	import pl.engine.model.MapGrid;
	import pl.engine.model.Model;
	import pl.engine.renderer.IMapRenderer;
	import pl.engine.renderer.MapRenderer;
	import pl.engine.renderer.logic.ILogicRenderer;
	import pl.engine.renderer.logic.LogicRenderer;
	import pl.engine.service.MapTerrainProvider;
	import pl.engine.ui.KeysInput;
	import pl.engine.ui.UI;
	import pl.engine.ui.gui.panel.InfoPanel;
	import pl.engine.view.View;
	import pl.textures.TextureID;
	import pl.textures.Textures;
	import pl.world.actors.proto.IActor;

	import starling.core.Starling;
	import starling.display.Sprite;
	import starling.events.Event;
	import starling.events.ResizeEvent;

	import swc.InfoPanelMc;

	import flash.geom.Point;

	/**
	 * @author michalr
	 */
	public class IsoEngine extends Sprite implements IIsoEngine
	{
		private var view:View;
		private var model:IModel;
		private var renderer:IMapRenderer;
		private var logicRenderer:ILogicRenderer;
		private var keysInput:KeysInput;

		public function IsoEngine()
		{
			Textures.initTexturesCollection();
			UI.setCursorMode( UI.SELECT );
			model = Model.factory( Textures.getSingleTexture( TextureID.BASE ) );
			view = new View();
			logicRenderer = LogicRenderer.factory( model );
			logicRenderer.setUpdateGraphicsHandler( updateWorld );
			logicRenderer.start();
			addChild( view );
			addChild( InfoPanel.getInstance( new InfoPanelMc ) );

			InfoPanel.getInstance().setBaseTextureSize( MapGrid.ISO_W, MapGrid.ISO_H );
			InfoPanel.getInstance().setRectTileDimension( MapGrid.TILE_W, MapGrid.TILE_H );
			

			keysInput = KeysInput.factory( this );
			model.setTerrainReadyHandler( terrainReadyHandler );
			addEventListener( Event.ADDED_TO_STAGE, onATS );
		}

		public function generateDefaultTerain( dimX:uint, dimY:uint ):void
		{
			var tp:MapTerrainProvider = new MapTerrainProvider();
			tp.provideTerrainTo( model, dimX, dimY );
			Camera.lookAtTileCenter( 2, 2 );
			renderer = new MapRenderer( model, view, logicRenderer );
			resize();
		}

		public function addActor( actor:IActor ):void
		{
			logicRenderer.addActor( actor );
			updateWorld();
		}

		public function get isoCamera():ICameraIsoParams
		{
			return Camera.iso;
		}

		public function get positionIsoUnderCursor():Point
		{
			var p:Point = UI.cursor.getIsoPosition();
			return p;
		}

		public function get positionRectUnderCursor():Point
		{
			var pi:Point = UI.cursor.getIsoPosition();
			var p:Point = Camera.convertIsoToRect( pi.x, pi.y );
			return p;
		}

		public function getTilePositionUnderCursor():Point
		{
			var p:Point = positionRectUnderCursor;
			return new Point( Math.floor( p.x / MapGrid.TILE_W ), Math.floor( p.y / MapGrid.TILE_H ) );
		}

		public function selectTile( tx:uint, ty:uint ):void
		{
			model.getTileById( tx, ty ).isSelected = true;
			model.getTileById( tx, ty ).textures[0] = TextureID.BASE;
		}

		public function updateWorld():void
		{
			Camera.updateScreenSize();
			if (renderer != null) renderer.render();
		}

		public function moveActorTo( actor:IActor, position:Point ):void
		{
			var path:Vector.<Point> = new Vector.<Point>;
			path.push( new Point( actor.x, actor.y ) );
			path.push( position );
			actor.setMovePath( path );
		}

		private function resize():void
		{
			InfoPanel.getInstance().x = Math.floor( Starling.current.stage.stageWidth - InfoPanel.getInstance().width );
			InfoPanel.getInstance().y = 0;
			InfoPanel.getInstance().setBGHeight( Starling.current.stage.stageHeight );

			updateWorld();
		}

		private function terrainReadyHandler():void
		{
			Camera.init();
			Camera.updateScreenSize();
			InfoPanel.getInstance().setMapTilesCount( MapGrid.GRID_W_COUNT, MapGrid.GRID_H_COUNT );
		}

		private function onStageResize( event:ResizeEvent = null ):void
		{
			resize();
		}

		private function onATS( event:Event ):void
		{
			if (renderer != null) resize();
			stage.addEventListener( ResizeEvent.RESIZE, onStageResize );
		}
	}
}
